﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace 修为尽失.辅助.exts
{
    public static class Enumeration
    {
        public static int RandomEnum(this Enum e)
        {
            var et = e.GetType();
            var n = Enum.GetNames(et).Length;
            return new Random(Guid.NewGuid().GetHashCode()).Next(n);
        }

        public static string GetDescription(this Enum @this) => Common._CacheDescriptions.GetOrAdd(@this, (Func<Enum, string>) (key =>
        {
            var field = key.GetType().GetField(key.ToString());
            return (field == (FieldInfo) null) ? key.GetDescriptions(",") : Common.GetDescription(field);
        }));

        public static string GetDescriptions(this Enum @this, string separator = ",")
        {
            var strArray1 = @this.ToString().Split(',');
            var strArray2 = new string[strArray1.Length];
            var type = @this.GetType();
            for (var index = 0; index < strArray1.Length; ++index)
            {
                var field = type.GetField(strArray1[index].Trim());
                if (!(field == (FieldInfo) null))
                    strArray2[index] = Common.GetDescription(field);
            }

            return string.Join(separator, strArray2);
        }

        public static string GetEnumNameByValue<T>(this object value)
        {
            var enumType = typeof(T);
            if (enumType.IsEnum)
                return Enum.GetName(enumType, value);
            throw new InvalidCastException("必须是枚举类型才能获取枚举名称。");
        }

        public static bool Has(this Enum value, Enum target)
        {
            Guard.ArgumentNotNull((object) value, "Enum value");
            Guard.ArgumentNotNull((object) target, "Enum target");
            if (value.GetType() != target.GetType())
                return false;
            return (value.GetHashCode() & target.GetHashCode()) == target.GetHashCode();
        }

        public static T Remove<T>(this Enum value, Enum target)
        {
            Guard.ArgumentNotNull((object) value, "Enum value");
            Guard.ArgumentNotNull((object) target, "Enum target");
            return (value.GetHashCode() & (~target.GetHashCode())).ToEnum<T>();
        }

        public static T ToEnum<T>(this string name)
        {
            if (typeof(T).IsEnum)
                return (T) Enum.Parse(typeof(T), name, true);
            throw new InvalidCastException("必须是枚举类型才能转换。");
        }

        public static T ToEnum<T>(this int value) => value.ToString().ToEnum<T>();

        public static T ToEnum<T>(this string[] values)
        {
            Guard.ArgumentNotNull((object) values, nameof(values));
            if (!typeof(T).IsEnum)
                throw new InvalidCastException("必须是枚举类型才能转换。");
            var stringList = new List<string>();
            foreach (var name in values)
                stringList.Add(name.ToEnum<T>().ToString());
            return string.Join(",", stringList.ToArray()).ToEnum<T>();
        }

        public static T ToEnumByValue<T>(this object value) => value.GetEnumNameByValue<T>().ToEnum<T>();
    }
}